package com.fengye.serialization.engine;

import com.fengye.serialization.common.SerializeType;
import com.fengye.serialization.serializer.Serializer;
import com.fengye.serialization.serializer.impl.*;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * 序列化引擎
 *
 * @Author fengye
 * @Date 2023/2/12 18:03
 **/
public class SerializerEngine {

    private static final Logger logger = LoggerFactory.getLogger(SerializerEngine.class);

    /** 序列化工具缓存 */
    private static final Map<SerializeType, Serializer> serializerMap = Maps.newConcurrentMap();

    static {
        serializerMap.put(SerializeType.DEFAULT_JAVA, new DefaultJavaSerializer());
        serializerMap.put(SerializeType.HESSIAN, new HessianSerializer());
        serializerMap.put(SerializeType.HESSIAN2, new Hessian2Serializer());
        serializerMap.put(SerializeType.FASTJSON, new FASTJSONSerializer());
        serializerMap.put(SerializeType.JSON, new JSONSerializer());
        serializerMap.put(SerializeType.XML, new XmlSerializer());
        serializerMap.put(SerializeType.PROTOSTUFF, new ProtoStuffSerializer());
        serializerMap.put(SerializeType.MARSHALLING, new MarshallingSerializer());
    }

    /**
     * 进行序列化
     *
     * @param obj
     * @param serializeType
     * @return
     * @param <T>
     */
    public static <T> byte[] serialize(T obj, String serializeType) {
        SerializeType serialize = SerializeType.queryByType(serializeType);
        logger.info(serialize.getSerializeType());
        if(serialize == null) {
            throw new RuntimeException("serialize is null");
        }

        Serializer serializer = serializerMap.get(serialize);
        if(serializer == null) {
            throw new RuntimeException("serialize error");
        }

        try {
            return serializer.serialize(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 反序列话
     *
     * @param data
     * @param clazz
     * @param serializeType
     * @return
     * @param <T>
     */
    public static <T> T deserialize(byte[] data, Class<T> clazz, String serializeType) {
        SerializeType serialize = SerializeType.queryByType(serializeType) ;
        if(serialize == null) {
            throw new RuntimeException("deserialize is null");
        }

        Serializer serializer = serializerMap.get(serialize);
        if(serializer == null) {
            throw new RuntimeException("deserialize error");
        }

        try {
            return serializer.deserialize(data, clazz);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
